package com.sxhuayuan.parking.entity;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;

import com.sxhuayuan.parking.utils.DateUtils;

import lombok.extern.log4j.Log4j2;

/**
 * 停车计费规则
 * 
 * @author gy
 */
@Entity
@Table(name = "hypk_park_charge_rule")
@Log4j2
public class ParkChargeRule extends BaseEntity {

	private static final long serialVersionUID = 8725599663247260728L;

	private String name;

	private Long parkingLotId;

	private ChargePolicy policy;

	// 收费时段
	private LocalTime beginTime;

	private LocalTime endTime;

	// 计费单元
	private Float unitHour;

	// 单价
	private Float unitPrice;

	// 单日收费上限
	private Float dailyFeeCap;

	private String rules;

	/** 收费策略 */
	public enum ChargePolicy {

		/** 按次收费 */
		byTimes,
		/** 按时间收费 */
		byTime,
		/** 按自然天，如果是每24h收费应该设置为按时间收费 */
		byDay,
		/** 其他类型 */
		others
	}

	@NotNull
	@Column(length = 128)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@NotNull
	@Column(nullable = false)
	public Long getParkingLotId() {
		return parkingLotId;
	}

	public void setParkingLotId(Long parkingLotId) {
		this.parkingLotId = parkingLotId;
	}

	@NotNull
	@Column(nullable = false)
	public ChargePolicy getPolicy() {
		return policy;
	}

	public void setPolicy(ChargePolicy policy) {
		this.policy = policy;
	}

	public LocalTime getBeginTime() {
		return beginTime;
	}

	public void setBeginTime(LocalTime beginTime) {
		this.beginTime = beginTime;
	}

	public LocalTime getEndTime() {
		return endTime;
	}

	public void setEndTime(LocalTime endTime) {
		this.endTime = endTime;
	}

	@Column(scale = 2, precision = 2)
	public Float getUnitHour() {
		return unitHour;
	}

	public void setUnitHour(Float unitHour) {
		this.unitHour = unitHour;
	}

	@Column(scale = 2, precision = 2)
	public Float getUnitPrice() {
		return unitPrice;
	}

	public void setUnitPrice(Float unitPrice) {
		this.unitPrice = unitPrice;
	}

	@Column(scale = 2, precision = 2)
	public Float getDailyFeeCap() {
		return dailyFeeCap;
	}

	public void setDailyFeeCap(Float dailyFeeCap) {
		this.dailyFeeCap = dailyFeeCap;
	}

	@Column(length = 2000)
	public String getRules() {
		return rules;
	}

	public void setRules(String rules) {
		this.rules = rules;
	}

	@Transient
	public Float calculateFee(Date begin, Date end, ReductionRule reductionRule) {
		if (begin == null || end == null || begin.after(end)) {
			return 0f;
		}
		float fee = 0f;
		switch (policy) {
		case byDay:
			fee = DateUtils.diff(begin, end, Calendar.DAY_OF_YEAR);
			break;
		case byTimes:
			fee = this.unitPrice;
			break;
		case byTime:
			// 一天一天算，每天有上限，也可能有免费时段
			long days = DateUtils.diff(begin, end, Calendar.DAY_OF_YEAR);

			String fmt = "HH:mm:ss";
			// 第一天
			LocalTime _beginTime = LocalTime.parse(DateUtils.format(begin, fmt));
			LocalTime _endTime = LocalTime.parse(DateUtils.format(end, fmt));
			if (log.isDebugEnabled()) {
				log.debug("_beginTime={}, _endTime={}", _beginTime, _endTime);
			}
			if (_beginTime.isBefore(this.beginTime)) {
				_beginTime = beginTime;
			}
			if (_endTime.isAfter(this.endTime)) {
				_endTime = endTime;
			}
			if (log.isDebugEnabled()) {
				log.debug("首日计费时段:{}->{}", _beginTime, _endTime);
			}
			for (int i = 0; i < days; i++) {
				// 分钟数
				long secondsDiff = DateUtils.diff(begin, end, Calendar.SECOND);
				fee = secondsDiff / (unitHour * 60f) * unitPrice;
			}

			break;
		default:
			break;
		}
		return setScale(fee);
	}

	private Float setScale(Float fee) {
		return new BigDecimal(fee).setScale(2, RoundingMode.HALF_UP).floatValue();
	}
}
